package com.xbongbong.paas.script.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.pojo.dto.FixDataJobDTO;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.pro.config.ProBaseConfig;
import com.xbongbong.pro.constant.XbbProConstant;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.WorkOrderEntity;
import com.xbongbong.saas.domain.entity.WorkOrderExplainEntity;
import com.xbongbong.saas.domain.entity.WorkOrderFlowNodeEntity;
import com.xbongbong.saas.enums.WorkOrderStatusEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.WorkOrderEnum;
import com.xbongbong.saas.model.WorkOrderFlowNodeModel;
import com.xbongbong.saas.model.WorkOrderModel;
import com.xbongbong.saas.model.impl.WorkOrderExplainModelImpl;
import com.xbongbong.saas.script.help.InitExplainsHelper;
import com.xbongbong.saas.script.tempenum.TempProductEnum;
import com.xbongbong.saas.script.tempenum.TempWorkOrderEnum;
import com.xbongbong.sys.model.CompanyModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.http.MediaType;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 工单刷解释、数据脚本
 * @author xinpeng.jiang
 * @date 2021/3/9 16:56
 * @version 1.0
 * @since V1.0
 */
@RestController
@RequestMapping(XbbProConstant.API_ROOT_PREFIX + "/script/workOrder")
public class WorkOrderScriptController {
    private static final Logger LOG = LoggerFactory.getLogger(WorkOrderScriptController.class);
    @Resource
    private ProBaseConfig proBaseConfig;
    @Resource
    private CompanyModel companyModel;
    @Resource
    private PaasRedisHelper paasRedisHelper;
    @Resource
    private WorkOrderExplainModelImpl workOrderExplainModel;
    @Resource
    private WorkOrderModel workOrderModel;
    @Resource
    private WorkOrderFlowNodeModel workOrderFlowNodeModel;

    @RequestMapping(value = "/addWorkOrderExplainShipStatus", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public void addWorkOrderExplainShipStatus(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        LocaleContextHolder.setLocale(Locale.CHINA);
        long start = DateTimeUtil.getInt();
        List<String> corpidList = fixDataJobDTO.getCorpidList();
        if (CollectionsUtil.isEmpty(corpidList)) {
            corpidList = companyModel.getCorpidList();
            corpidList.add("0");
        }
        LOG.warn("数据库中共有公司{}家", corpidList.size());

        // 初始化要加的字段
        WorkOrderEnum shipStatus = WorkOrderEnum.SHIP_STATUS;
        FieldAttrEntity newFieldAttrEntity = InitExplainsHelper.setField(shipStatus.getAttr(), shipStatus.getAttrName(), shipStatus.getSaasAttr(), shipStatus.getFieldType(), shipStatus.getSetType(), shipStatus.getShowType(), shipStatus.getEditHide(), shipStatus.getDesignEditable());
        try {
            Method method = TempWorkOrderEnum.class.getMethod("init" + newFieldAttrEntity.getSaasAttr().substring(0, 1).toUpperCase() + newFieldAttrEntity.getSaasAttr().substring(1), FieldAttrEntity.class);
            method.invoke(TempProductEnum.class, newFieldAttrEntity);
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            LOG.error("反射调用方法出错！", e);
        }

        int corpidCount = 0;
        int businessType = XbbRefTypeEnum.WORK_ORDER.getCode();
        Map<String, Object> selectParams = new HashMap<>(3);
        selectParams.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        selectParams.put("businessType", businessType);
        // 公司列表
        for (String corpid : corpidList) {
            selectParams.put(ParameterConstant.CORPID, corpid);
            // 未处理解释列表
            List<WorkOrderExplainEntity> noHandleExplainsList = workOrderExplainModel.getNoHandleExplainsByFindEntitys(selectParams);
            for (WorkOrderExplainEntity explainEntity : noHandleExplainsList) {
                if (Objects.equals("[]", explainEntity.getExplains())) {
                    continue;
                }
                // 解释列表转字段实体
                List<FieldAttrEntity> fieldAttrEntityList = JSONArray.parseArray(explainEntity.getExplains(), FieldAttrEntity.class);
                int index = 0;
                for (int i = 0; i < fieldAttrEntityList.size(); i++) {
                    FieldAttrEntity fieldAttrEntity = fieldAttrEntityList.get(i);
                    //插入到当前字段后面
                    if (Objects.equals(fieldAttrEntity.getAttr(), WorkOrderEnum.SPARE_PARTS.getAttr())) {
                        index = i + 1;
                    }
                    if (Objects.equals(fieldAttrEntity.getAttr(), newFieldAttrEntity.getAttr())) {
                        index = 0;
                        LOG.warn("公司{},已经存在{}字段", corpid, fieldAttrEntity.getAttr());
                        break;
                    }
                }

                if (index != 0) {
                    fieldAttrEntityList.add(index, newFieldAttrEntity);
                    String explains = JSONObject.toJSONString(fieldAttrEntityList);
                    explainEntity.setExplains(explains);
                    workOrderExplainModel.update(explainEntity);
                }
            }
            // 删redis中缓存
            String key = corpid + StringConstant.CROSS + businessType;
            paasRedisHelper.removeValue(RedisPrefixConstant.FIELD_EXPLANATION, key);

            corpidCount++;
            LOG.warn("公司{}:{}/{}", corpid, corpidCount, corpidList.size());
        }

        LOG.warn("consume:{}", (DateTimeUtil.getInt() - start));
        LOG.warn("操作成功");
    }


    /**
     * Description: 修复工单的开始和结束时间
     * @param fixDataJobDTO
	 * @param br
     * @return void
     * @throws
     * @author 魏荣杰
     * @date 2022/9/20 14:09
     * @since
     */
    @RequestMapping(value = "/fixTimeOut", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public void fixTimeOut(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        LocaleContextHolder.setLocale(Locale.CHINA);
        long start = DateTimeUtil.getInt();

        Long formId = fixDataJobDTO.getFormId();
        if (Objects.isNull(formId)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, "formId为空");
        }

        List<String> corpidList = fixDataJobDTO.getCorpidList();

        if (CollectionsUtil.isNotEmpty(corpidList)) {
            String corpid = corpidList.get(0);
            Map<String, Object> param = new HashMap<>();
            param.put(ParameterConstant.CORPID, corpid);
            param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
            param.put("statusIn", Arrays.asList(WorkOrderStatusEnum.ONGOING.getCode(), WorkOrderStatusEnum.FINISH.getCode(), WorkOrderStatusEnum.CLOSE.getCode()));
            param.put("startTime", 0);
            param.put("formId", formId);

            List<WorkOrderEntity> workOrderEntities = workOrderModel.findEntitysWithoutSub(param);

            if (CollectionsUtil.isNotEmpty(workOrderEntities)) {
                LOG.warn("workOrderEntities.size: {}", workOrderEntities.size());
                List<Long> ids = workOrderEntities.stream().map(WorkOrderEntity::getId).collect(Collectors.toList());

                Map<String, Object> map = new HashMap<>();
                map.put(ParameterConstant.CORPID, corpid);
                map.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
                map.put(ParameterConstant.IDS, DelEnum.NORMAL.getDel());
                map.put("workOrderIdIn", ids);
                map.put(ParameterConstant.ORDER_BY_STR, "add_time");
                List<WorkOrderFlowNodeEntity> workOrderFlowNodeEntities = workOrderFlowNodeModel.findEntitys(map);
                Map<Long, List<WorkOrderFlowNodeEntity>> nodeMap = workOrderFlowNodeEntities.stream().collect(Collectors.groupingBy(WorkOrderFlowNodeEntity::getWorkOrderId));

                for (WorkOrderEntity workOrderEntity : workOrderEntities) {
                    List<WorkOrderFlowNodeEntity> nodeEntityList = nodeMap.get(workOrderEntity.getId());
                    if (CollectionsUtil.isNotEmpty(nodeEntityList)) {
                        workOrderEntity.setStartTime(nodeEntityList.get(0).getStartTime());
                        workOrderEntity.setEndTime(nodeEntityList.get(nodeEntityList.size() -1 ).getEndTime());
                    }
                }

                workOrderModel.updateBatchList(workOrderEntities, corpid);
            }

        }

        LOG.warn("consume:{}", (DateTimeUtil.getInt() - start));
        LOG.warn("操作成功");
    }

}
